package org.noote.libs.computervision.function;

import org.noote.libs.computervision.Intensity;

//Zhang-Suen thinning
// http://rsb.info.nih.gov/ij/developer/source/ij/process/BinaryProcessor.java.html

public class ZhuanSuenThinning {
	
	public void thinning(Intensity buffer, int limitMin, int thin_maxpass)
	{
		// 	squelettisation
		int pass = 0;
		while(pass<thin_maxpass) // not used
		{
			if(zhansuen_thin(buffer, pass++, limitMin) == 0)
				break;
		}
	}
	
	static int[] table  =
	{0,0,0,1,0,0,1,3,0,0,3,1,1,0,1,3,0,0,0,0,0,0,0,0,2,0,2,0,3,0,3,3,
	 0,0,0,0,0,0,0,0,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,3,0,2,2,
	 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
	 2,0,0,0,0,0,0,0,2,0,0,0,2,0,0,0,3,0,0,0,0,0,0,0,3,0,0,0,3,0,2,0,
	 0,0,3,1,0,0,1,3,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,
	 3,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
	 2,3,1,3,0,0,1,3,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
	 2,3,0,1,0,0,0,1,0,0,0,0,0,0,0,0,3,3,0,1,0,0,0,0,2,2,0,0,2,0,0,0};
	
	private int zhansuen_thin(Intensity buffer, int pass, int limitMin) {
	
		int p1, p2, p3, p4, p5, p6, p7, p8, p9;
		int _width = buffer.getWidth();
		int _height = buffer.getHeight();
		short _iEdge[] = buffer.getBuffer(); 
	        
	    short [] pixels2 = new short[_width*_height];
	    for(int i=0; i<_width*_height; i++) pixels2[i] = _iEdge[i];
	    
	    int v, index, code;
	    int offset;
	    int pixelsRemoved = 0;
	    
	    for (int y=1; y<_height-1; y++) {
	        offset = y * _width;
	        for (int x=1; x<_width-1; x++) {
	            p5 = pixels2[offset]&0xff;
	            v = p5;
	            if (v>limitMin) {
	                p1 = pixels2[offset-_width-1]&0xff;
	                p2 = pixels2[offset-_width]&0xff;
	                p3 = pixels2[offset-_width+1]&0xff;
	                p4 = pixels2[offset-1]&0xff;
	                p6 = pixels2[offset+1]&0xff;
	                p7 = pixels2[offset+_width-1]&0xff;
	                p8 = pixels2[offset+_width]&0xff;
	                p9 = pixels2[offset+_width+1]&0xff;
	                index = 0;
	                if (p1>limitMin) index |= 1;
	                if (p2>limitMin) index |= 2;
	                if (p3>limitMin) index |= 4;
	                if (p6>limitMin) index |= 8;
	                if (p9>limitMin) index |= 16;
	                if (p8>limitMin) index |= 32;
	                if (p7>limitMin) index |= 64;
	                if (p4>limitMin) index |= 128;
	                code = table[index];
	                if ((pass&1)==1) { //odd pass
	                if (code==2 || code==3) {
	                    v = 0;
	                    pixelsRemoved++;
	                }
	            } else { //even pass
                    if (code==1 || code==3) {
                        v = 0;
                        pixelsRemoved++;
                    }
                }
            }
            _iEdge[offset++] = (byte)v;
        }
    }
    return pixelsRemoved;
}
}
